
package nl.rainbowsheep.reisorg.rest.service.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Map;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.MapKeyJoinColumn;
import javax.persistence.PostLoad;
import javax.persistence.PostUpdate;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import nl.rainbowsheep.reisorg.rest.service.util.Localizer;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

@Entity
@Table(name = "countries")
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
public class Country implements Serializable, ILocalized {
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "country_id")
    private Long id;

    @Column(name = "name")
    private String name;
    
    /*
    /   Hibernate doesn't know that an entity has changed when the changed field is transient.
    /   To work around this, we don't make em transient and fill em with meaningless data (No relation to locale, last updated value is stored).
    /   
    /   We need to do this if we want to use persistence interceptors. Hibernate doenst handle changes in Maps very well.
    */
    @Column(name = "fake_description")
    private String description;

    @ElementCollection(fetch = FetchType.EAGER)
    @CollectionTable(name = "countries_locale", joinColumns = @JoinColumn(name = "countries_fk"))
    @MapKeyJoinColumn(name = "languages_fk")
    private Map<Language, CountryLocalized> locale;

    /*
    /
    / Added to force a change in the entity. Not always valid but some entities will have valid use cases.
    /
    */
    @Column(name="last_update")
    private Timestamp lastUpdate;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @JsonIgnore
    @Override
    public Map getLocale() {
        return locale;
    }

    @Override
    public void setLocale(Map locale) {
        this.locale = locale;
    }

    public String getDescription() {
        return this.description;
    }

    public void setDescription(String description) {

        this.description = description;
    }

    public Timestamp getLastUpdate() {
        return lastUpdate;
    }

    public void setLastUpdate(Timestamp lastUpdate) {
        this.lastUpdate = lastUpdate;
    }


    //Transfers the needed data from the map to the according values.
    @Override
    @PostLoad //After loading from DB
    @PostUpdate //After update
    public void localize() {
        CountryLocalized localizedObject = (CountryLocalized) Localizer.getLocalizedObject(this.locale, CountryLocalized.class);
        if (localizedObject != null) {
            this.description = localizedObject.getDescription();
        }
    }

    //Transfers localized data to the map
    @Override
    @PreUpdate //Before an update
    @PrePersist //Before insert
    public void parseLocalizedData() {
        CountryLocalized localizedObject = (CountryLocalized) Localizer.getLocalizedObject(this.locale, CountryLocalized.class);
        localizedObject.setDescription(this.description);
    }
}
